import sqlalchemy.exc
import grpc
from sqlalchemy import update
from sqlalchemy.sql import select
from loguru import logger
from protos import user_pb2, user_pb2_grpc
from models.user import User
from google.protobuf import  empty_pb2
from utils import pwdutil
class UserServicer(user_pb2_grpc.UserServicer):
    async def CreateUser(self, request:user_pb2.CreateUserRequest, context, session):
        mobile = request.mobile
        try:
            async with session.begin():
                user = User(mobile=mobile)
                session.add(user)
            response = user_pb2.UserInfoResponse(user=user.to_dict())
            return response
        except sqlalchemy.exc.IntegrityError:
            context.set_code(grpc.StatusCode.ALREADY_EXISTS)
            context.set_details('手机号码已存在！')
    async def GetUserById(self, request:user_pb2.IdRequest, context, session):
        try:
            user_id = request.id
            async with session.begin():
                query = await session.execute(select(User).where(User.id == user_id))
                user = query.scalar()
                if not user:
                    context.set_code(grpc.StatusCode.NOT_FOUND)
                    context.set_details('用户不存在！')
                else:
                    response = user_pb2.UserInfoResponse(user=user.to_dict())
                    return response
        except Exception as e:
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details('服务器错误!')

    async def GetUserByMobile(self, request:user_pb2.MobileRequest, context, session):
        try:
            mobile = request.mobile
            async with session.begin():
                query = await session.execute(select(User).where(User.mobile == mobile))
                user = query.scalar()
                if not user:
                    context.set_code(grpc.StatusCode.NOT_FOUND)
                    context.set_details('用户不存在！')
                else:
                    response = user_pb2.UserInfoResponse(user=user.to_dict())
                    return response
        except Exception as e:
            print("GetUserByMobile", e)
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details('服务器错误!')
    async def UpdateAvatar(self, request:user_pb2.AvatarRequest, context, session):
        try:
            user_id = request.id
            avatar = request.avatar
            async with session.begin():
                stmt = update(User).where(User.id == user_id).values(avatar=avatar)
                result = await session.execute(stmt)
                rowcount = result.rowcount
                if rowcount == 0:
                    context.set_code(grpc.StatusCode.NOT_FOUND)
                    context.set_details('用户不存在！')
                else:
                    response = empty_pb2.Empty()
                    return response
        except Exception as e:
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details('服务器错误!')
    async def UpdateUsername(self, request, context, session):
        try:
            user_id = request.id
            username = request.username
            stmt = update(User).where(User.id == user_id).values(username=username)
            result = await session.execute(stmt)
            rowcount = result.rowcount
            if rowcount == 0:
                context.set_code(grpc.StatusCode.NOT_FOUND)
                context.set_details('用户不存在！')
            else:
                response = empty_pb2.Empty()
                return response
        except Exception as e:
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details('服务器错误!')


    async def UpdatePassword(self, request, context, session):
        try:
            user_id = request.id
            password = request.password
            if not password:
                context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
                context.set_details('密码不能为空！')
                return
            hashed_password = pwdutil.hash_password(password)
            async with session.begin():
                stmt = update(User).where(User.id == user_id).values(password=hashed_password)
                result = await session.execute(stmt)
                rowcount = result.rowcount
                if rowcount == 0:
                    context.set_code(grpc.StatusCode.NOT_FOUND)
                    context.set_details('用户不存在！')
                else:
                    print("密码已修改")
                    response = empty_pb2.Empty()
                    return response
        except Exception as e:
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details('服务器错误!')

    async def GetUserList(self, request:user_pb2.PageRequest, context, session):
        try:
            page = request.page
            size = request.size
            offset = (page - 1) * size
            async with session.begin():
                query = await session.execute(select(User).offset(offset).limit(size))
                result = query.scalars().fetchall()
                users = []
                for user in result:
                    users.append(user.to_dict())
                response = user_pb2.UserListResponse(users=users)
            return response
        except Exception as e:
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details('服务器错误!')


    async def VerifyUser(self, request: user_pb2.VerifyUserRequest, context, session):
        async with session.begin():
            mobile = request.mobile
            password = request.password
            result = await session.execute(select(User).where(User.mobile==mobile))
            user = result.scalar()
            if not user:
                context.set_code(grpc.StatusCode.NOT_FOUND)
                context.set_details('该用户不存在！')
            if not pwdutil.check_password(password, user.password):
                context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
                context.set_details('密码错误！')
            reponse = user_pb2.UserInfoResponse(user=user.to_dict())
            return reponse

    async def GetOrCreateUserByMobile(self, request:user_pb2.MobileRequest, context, session):
        try:
            mobile = request.mobile
            async with session.begin():
                query = await session.execute(select(User).where(User.mobile==mobile))
                user = query.scalar()
                if not user:
                    user = User(mobile=mobile)
                    session.add(user)
            response = user_pb2.UserInfoResponse(user=user.to_dict())
            logger.info('收到信息！！！')
            return response
        except Exception as e:
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details('服务器错误!')
